package se.talento.restlet;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import org.restlet.resource.ServerResource;

/**
 * Base resource class that supports common behaviours or attributes shared by
 * all resources.
 * 
 */
public abstract class BaseResource extends ServerResource {
	private static final Logger log = Logger.getLogger(DefaultResource.class.getName());	

    /**
     * Returns the map of items managed by this application.
     * 
     * @return the map of items managed by this application.
     */
    protected ConcurrentMap<String, Item> getItems() {
        return ((TestApplication) getApplication()).getItems();
    }

    protected Item createItem(Item item) {
    	log.info("Item to create: " + item.toString());
    	
        EntityManager em = EMF.get().createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try
        {
            tx.begin();
            em.persist(item);
            tx.commit();
        }
        finally
        {
            if (tx.isActive())
            {
                tx.rollback();
            }
        }
        em.close();
        
    	log.info("Created item: " + item.toString());
        
        return item;
    }
    
    protected void deleteItem(Long id) {
    	log.info("Item to delete: " + id);
    	
        EntityManager em = EMF.get().createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try
        {
            tx.begin();
            em.remove(em.find(Item.class, id));
            tx.commit();
        }
        finally
        {
            if (tx.isActive())
            {
                tx.rollback();
            }
        }
        em.close();
        
        log.info("Item " + id + " was deleted");
    }
    
    protected Item updateItem(Item item) {
    	log.info("Item to update: " + item);
    	Item updatedItem = null;
        EntityManager em = EMF.get().createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try
        {
            tx.begin();
            updatedItem = em.merge(item);
            tx.commit();
        }
        finally
        {
            if (tx.isActive())
            {
                tx.rollback();
            }
        }
        em.close();
        
    	log.info("Updated item: " + item);

    	return updatedItem;
    }

	@SuppressWarnings("unchecked")
	protected List getAllItems() {
    	List items = new ArrayList();
        EntityManager em = EMF.get().createEntityManager();
        EntityTransaction tx = em.getTransaction();
        Query query = em.createQuery("SELECT i FROM Item i");
        try
        {
            tx.begin();
            items = query.getResultList();
            tx.commit();
        }
        finally
        {
            if (tx.isActive())
            {
                tx.rollback();
            }
        }
        em.close();
        
        log.info("Got " + (items == null ? "0" : items.size()) + " nr of items");

        return items;
    }
    
	protected Item getItem(Long id) {
		log.info("Getting item: " + id);
		
    	Item item = null;
        EntityManager em = EMF.get().createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try
        {
            tx.begin();
            item = em.find(Item.class, id);
            tx.commit();
        }
        finally
        {
            if (tx.isActive())
            {
                tx.rollback();
            }
        }
        em.close();

        log.info("Got item: " + item);
        
        return item;
    }
    
    @SuppressWarnings("unchecked")
	protected Item getItem(String name) {
		log.info("Getting item: " + name);

		Item item = null;
        EntityManager em = EMF.get().createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try
        {
            tx.begin();
            // Numbered parameter does not work for some reason.
//            Query query = em.createQuery("SELECT i FROM Item i WHERE i.name = ?1");
//            query.setParameter(1, name);
            Query query = em.createQuery("SELECT i FROM Item i WHERE i.name = :itemName");
            query.setParameter("itemName", name);
            List results = query.getResultList();
            
            log.info("Results size: " + results.size());
            
            Iterator it = results.iterator();
            if (it.hasNext()) {
            	item = (Item) it.next();
            }
            tx.commit();
        }
        finally
        {
            if (tx.isActive())
            {
                tx.rollback();
            }
        }
        em.close();
        
        log.info("Got item: " + item);

        return item;
    }
}
